﻿// Copyright (c) 2014 Bryan C. O'Connell
// http://wsubi.codeplex.com/license
// Purpose: Builds Command objects. Attempts to follow the 'Simple Factory' pattern.

using System;
using System.Collections.Generic;
using Wsubi.Code.Utilities;

namespace Wsubi.Code.Commands
{
    public class CommandFactory
    {
        private string _CommandText;
        private ICommand _Command;

        private const char SPACE = (char)32;

        public CommandFactory(string CommandText)
        {
            Guard.CheckForEmptyString(CommandText);
            _CommandText = CommandText;
        }

        public ICommand MakeCommand()
        {
            ParseCommand();
            return _Command;
        }

        private void ParseCommand()
        {
            string[] CommandSegments = SplitCommandTextIntoSegments();

            string Action = CommandSegments[0];            
            _Command = DetermineCommandType(Action);
            _Command.Target = CommandSegments[1];
            _Command.Params = _CommandText.Remove(0, (Action + SPACE + _Command.Target).Length).Trim();
        }

        private string[] SplitCommandTextIntoSegments()
        {            
            char[] Delimiter_Space = new char[] { SPACE };
            string[] CommandSegments = _CommandText.Split(Delimiter_Space, StringSplitOptions.RemoveEmptyEntries);

            // A Command MUST contain at least 2 segments (Ex: 'roll *'). If not, it's invalid.
            const int MINIMUM_SEGMENTS = 2;
            Guard.MinimumNumberOfArrayElements(CommandSegments, MINIMUM_SEGMENTS);
            return CommandSegments;
        }

        private ICommand DetermineCommandType(string Action)
        {
            ICommand CommandRequested = null;
            List<ICommand> PossibleCommands = BuildListOfPossibleCommands();

            // TODO: Could this logic loop be a 1-line LINQ statement?

            foreach (ICommand CurrentCommand in PossibleCommands) 
            {
                if (CurrentCommand.GetActionKeyword() == Action) {
                    CommandRequested = CurrentCommand;
                }
            }

            Guard.CheckForNullObject(CommandRequested);
            return CommandRequested;
        }

        /// <summary>Add to the list within this function whenever a new Command is created.</summary>
        private List<ICommand> BuildListOfPossibleCommands()
        {
            List<ICommand> PossibleCommands = new List<ICommand>();
            PossibleCommands.Add(new Help());
            PossibleCommands.Add(new Info());
            PossibleCommands.Add(new List());
            PossibleCommands.Add(new Query());
            PossibleCommands.Add(new Queue());
            PossibleCommands.Add(new Roll());
            PossibleCommands.Add(new Run());
            PossibleCommands.Add(new Search());

            return PossibleCommands;
        }
    }
}
